﻿//
// eCRAM, a monthly activity report web application
// Copyright (C) 2010  Aptea
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

using System.Data.Linq;
using System.Linq;
using eCRAM.Model;
using System.Collections.Generic;
using System;

namespace eCRAM.Dao
{
    /// <summary>
    /// Classe fournissants des méthodes utilitaires d'inteactions avec la bdd pour les Activités
    /// </summary>
    public static class ActivityRepository
    {
        public static IList<Activity> GetAll()
        {
            using (var context = new eCramDataContext())
            {
                var loadOptions = new DataLoadOptions();
                loadOptions.LoadWith<Activity>(a => a.ActivityType);
                loadOptions.LoadWith<Activity>(a => a.User);
                context.LoadOptions = loadOptions;
                return context.Activities.ToList();

            }
        }

        /// <summary>
        /// Create of activity
        /// </summary>
        /// <param name="activity"></param>
        public static void Create(Activity activity)
        {
            using (var context = new eCramDataContext())
            {
                activity.Id = Guid.NewGuid();
                context.Activities.InsertOnSubmit(activity);
                context.SubmitChanges();
            }
        }

        /// <summary>
        /// Delete activity
        /// </summary>
        /// <param name="activity"></param>
        public static void Delete(Activity activity)
        {
            using (var context = new eCramDataContext())
            {
                context.Activities.Attach(activity);
                context.Activities.DeleteOnSubmit(activity);
                context.SubmitChanges();
            }
        }

        /// <summary>
        /// Get activity by Id
        /// </summary>
        /// <param name="activityId"></param>
        /// <returns></returns>
        public static Activity GetById(Guid activityId)
        {
            using (var context = new eCramDataContext())
            {
                var loadOptions = new DataLoadOptions();
                loadOptions.LoadWith<Activity>(a => a.ActivityType);
                loadOptions.LoadWith<Activity>(a => a.User);
                loadOptions.LoadWith<Activity>(a => a.User_Activities);
                context.LoadOptions = loadOptions;

                return context.Activities.SingleOrDefault(a => a.Id == activityId);
            }
        }

        /// <summary>
        /// Get only activity list from start to limit 
        /// </summary>
        /// <param name="start"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public static IList<Activity> GetTop(int start, int limit)
        {
            using (var context = new eCramDataContext())
            {
                var loadOptions = new DataLoadOptions();
                loadOptions.LoadWith<Activity>(a => a.ActivityType);
                context.LoadOptions = loadOptions;
                return context.Activities
                    .Skip(start)
                    .Take(limit - start).ToList();
            }

        }

        /// <summary>
        /// Get the Activities Count in db
        /// </summary>
        /// <returns></returns>
        public static int GetCount(Func<Activity, bool> predicate)
        {
            using (var context = new eCramDataContext())
            {
                return context.Activities.Count(predicate);
            }
        }

        /// <summary>
        /// Tell us if activity is available to be createde or not (name must be unique)
        /// </summary>
        /// <param name="name"></param>
        /// <param name="activityId">activityId is not Empty, we just check if the name already exist 
        /// in db for an other activity, if not check if user name exist in db</param>
        /// <returns></returns>
        public static bool ActivityNameIsAvailable(string name, Guid activityId)
        {
            using (var context = new eCramDataContext())
            {
                if (activityId == Guid.Empty)
                {
                    return context.Activities.Where(a => a.Name == name).Any();
                }
                return context.Activities.Where(a => (a.Name == name) && (a.Id != activityId)).Any();
            }
        }


        public static IEnumerable<string> GetAllActivityName()
        {
            using (var context = new eCramDataContext())
            {
                return context.Activities.Select(a => a.Name).ToList();
            }
        }

        public static void Update(Activity activity)
        {
            using (var context = new eCramDataContext())
            {
                LinqTools.Update(activity, a => a.Id == activity.Id, context);
                context.SubmitChanges();
            }
        }

        public static IEnumerable<ActivityType> GetAllActivityTypes()
        {
            using (var context = new eCramDataContext())
            {
                return context.ActivityTypes.ToList();
            }
        }

        public static IEnumerable<Activity> GetUserActivityList(Guid idUser)
        {
            using (var context = new eCramDataContext())
            {
                var loadOptions = new DataLoadOptions();
                loadOptions.LoadWith<Activity>(a => a.ActivityType);

                context.LoadOptions = loadOptions;

                return
                    context.Activities.Where(
                        item => item.IsActive &&
                            (item.ActivityType.IsHoliday || item.User_Activities.Any(ua => ua.UserId == idUser)))
                            .ToList();
            }
        }

        public static IEnumerable<Activity> GetAvailableUserActivityListAndHolidays(Guid idUser)
        {
            using (var context = new eCramDataContext())
            {
                var loadOptions = new DataLoadOptions();
                loadOptions.LoadWith<Activity>(a => a.ActivityType);
                context.LoadOptions = loadOptions;

                return context.Activities.Where(item => item.IsActive && !item.User_Activities.Any(ua => ua.UserId == idUser)).ToList();
            }
        }


        public static IEnumerable<Activity> GetAvailableUserActivityList(Guid idUser)
        {
            using (var context = new eCramDataContext())
            {
                var loadOptions = new DataLoadOptions();
                loadOptions.LoadWith<Activity>(a => a.ActivityType);
                context.LoadOptions = loadOptions;

                return context.Activities.Where(item => item.IsActive && !item.ActivityType.IsHoliday && !item.User_Activities.Any(ua => ua.UserId == idUser)).ToList();
            }
        }

        public static IEnumerable<Activity> GetRestrictedActivityList(Guid idUser)
        {
            using (var context = new eCramDataContext())
            {
                var loadOptions = new DataLoadOptions();
                loadOptions.LoadWith<Activity>(a => a.ActivityType);
                context.LoadOptions = loadOptions;

                var user = context.Users.FirstOrDefault(u => u.Id == idUser);
                if (user == null || !(user.Role == (int)UserRole.Administrator || user.Role == (int)UserRole.ProjectLeader))
                {
                    return new List<Activity>();
                }

                if (user.Role == (int)UserRole.Administrator)
                {
                    return context.Activities.ToList();
                }

                return context.Activities.Where(a => a.ProjectLeader == idUser).ToList();
            }
        }
    }
}